package org.robert.export_client.easyexcel.write.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.fastjson.JSON;
import com.robert.common.commonutil.exception.AppException;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.robert.export_client.aop.ExcelDictAdapter;
import org.robert.export_client.easyexcel.write.IExcelExportService;
import org.robert.export_client.easyexcel.entity.WebRequest;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * ExcelDownLoad:
 *  excel下载器，需要配置EasyExcel的注解使用
 * @author zhaoshengtao
 * @date 2024/01/08
 */
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class ExcelExportDataService<T> extends WebRequest<T> implements IExcelExportService {

    private List<T> data;

    public ExcelExportDataService(HttpServletResponse response, List<T> data, Class<T> clazz){
        this.data = data;
        this.response = response;
        this.clazz = clazz;
    }
    public ExcelExportDataService(HttpServletResponse response, List<T> data, Class<T> clazz,
                                  Map<String, Map<String, String>> dictMap){
        this.data = data;
        this.response = response;
        this.clazz = clazz;
        this.dictMap = dictMap;
        if(org.apache.commons.collections4.MapUtils.isNotEmpty(dictMap)){
            this.checker = new ExcelDictAdapter<T>();
        }
    }

    public ExcelExportDataService(HttpServletResponse response, List<T> data, Class<T> clazz,
                                  Map<String, Map<String, String>> dictMap, String fileName){
        this.data = data;
        this.response = response;
        this.clazz = clazz;
        this.dictMap = dictMap;
        this.fileName = fileName;
        if(org.apache.commons.collections4.MapUtils.isNotEmpty(dictMap)){
            this.checker = new ExcelDictAdapter<T>();
        }
    }

    public ExcelExportDataService(HttpServletResponse response, List<T> data, Class<T> clazz,
                                  Map<String, Map<String, String>> dictMap, String fileName, String sheetName){
        this.data = data;
        this.response = response;
        this.clazz = clazz;
        this.dictMap = dictMap;
        this.fileName = fileName;
        this.sheetName = sheetName;
        if(org.apache.commons.collections4.MapUtils.isNotEmpty(dictMap)){
            this.checker = new ExcelDictAdapter<T>();
        }
    }

    /**
     * 同步下载到浏览器, 提供数据
     *
     */
    @Override
    public void exportToExcel() throws Exception {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        log.info("exportToExcel fileName={}", fileName);
        if(!check() || data == null){
            throw new AppException("500", "下载参数异常");
        }
        try{
            long start = System.currentTimeMillis();
            // 字典转换
            if(org.apache.commons.collections4.MapUtils.isNotEmpty(dictMap)
                    && CollectionUtils.isNotEmpty(data)){
                ExcelDictAdapter<T> checker = new ExcelDictAdapter<>();
                checker.setDict(data, dictMap);
            }
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode(this.fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这步很重要，需要在给前端返回的请求头中添加Content-Disposition字段，否则前端会取不到Content-Disposition的信息
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            EasyExcel.write(response.getOutputStream(), clazz)
                    .autoCloseStream(Boolean.FALSE).sheet(sheetName)
                    .doWrite(data);
            long endTime = System.currentTimeMillis() -start;
            log.info("exportToExcel run time: {} ms", endTime);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("code", "error");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }

}
